package com.xiaoma.lock.condition;

import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * ReentrantLock 显式锁
 *
 * Condition 显式条件
 *
 * 生产者、消费者协作模式
 */

public class ReentrantLockTest {

  private  int e = 1;

  private  int num = 30;

  //private  BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(num);

  private Queue<Integer> queue = new ArrayDeque<>(num);

  private Lock lock = new ReentrantLock();

  private Condition productCondition = lock.newCondition();

  private  Condition consumerConditon = lock.newCondition();

  public static void main(String[] args) throws InterruptedException {

    ReentrantLockTest reentrantLockTest = new ReentrantLockTest();

    for(int i = 0; i < reentrantLockTest.num; i++){
      new Thread(() -> {
        try {
          reentrantLockTest.producer();
//          Thread.sleep((int)(Math.random() * 100));
        } catch (InterruptedException e1) {
          e1.printStackTrace();
        }
      }).start();
    }

//    Thread.sleep(1000);

    for(int i = 0; i < reentrantLockTest.num; i++){
      new Thread(() -> {
        try {
          reentrantLockTest.consumer();
//          Thread.sleep((int)(Math.random() * 100));
        } catch (InterruptedException e1) {
          e1.printStackTrace();
        }
      }).start();
    }




  }

  public  void producer() throws InterruptedException {
    lock.lockInterruptibly();
    try{
      //队列满了,生产者阻塞等待
      if (queue.size() == num){
        productCondition.await();
      }
      queue.add(e++);
      System.out.println("producer" + Arrays.toString(queue.toArray()));
      consumerConditon.signal();//通知消费线程
    }finally {
      lock.unlock();
    }

  }

  public  void consumer() throws InterruptedException {
    lock.lockInterruptibly();
    try{
      //队列空的，消费者阻塞
      if (queue.isEmpty()){
        consumerConditon.await();
      }

      System.out.println("poll:" + queue.poll() + ",comsumer" + Arrays.toString(queue.toArray()));
      productCondition.signal();
    }finally {
      lock.unlock();
    }

  }

}
